#include <atomic>
#include <type_traits>
#include <utility>

// 前置声明
template <typename T> class shared_ptr;
template <typename T> class weak_ptr;
template <typename T> class enable_shared_from_this;

// 控制块基类（类型擦除，统一接口）
struct ControlBlockBase {
    std::atomic<size_t> strong_count;  // 强引用计数：记录有多少个shared_ptr指向对象
    std::atomic<size_t> weak_count;    // 弱引用计数：记录有多少个weak_ptr指向对象

/**
 * @brief 构造函数，初始化强引用计数和弱引用计数。
 *
 * 默认情况下，强引用计数和弱引用计数均初始化为1。
 */
    ControlBlockBase() : strong_count(1), weak_count(1) {}
    virtual ~ControlBlockBase() = default;
    virtual void destroy() = 0;  // 销毁对象（纯虚函数，由派生类实现）
};

// 控制块派生类（存储对象和删除器）
template <typename T, typename Deleter>
struct ControlBlock : ControlBlockBase {
    T* object;       // 管理的对象
    Deleter deleter; // 自定义删除器

    // 构造：接收对象指针和删除器
    ControlBlock(T* obj, Deleter del) : object(obj), deleter(std::move(del)) {}

    // 销毁对象（调用删除器）
    void destroy() override {
        deleter(object);  // 支持自定义删除逻辑（如delete[]、fclose等）
    }
};

// 辅助：默认删除器（处理普通指针和数组）
template <typename T>
struct DefaultDeleter {
    void operator()(T* p) const { delete p; }
};
template <typename T>
struct DefaultDeleter<T[]> {
    void operator()(T* p) const { delete[] p; }
};

// enable_shared_from_this：允许对象获取自身的shared_ptr
template <typename T>
class enable_shared_from_this {
protected:
    enable_shared_from_this() = default;
    enable_shared_from_this(const enable_shared_from_this&) = default;
    enable_shared_from_this& operator=(const enable_shared_from_this&) = default;
    ~enable_shared_from_this() = default;

public:
    shared_ptr<T> shared_from_this() {
        return shared_ptr<T>(weak_this);
    }
    shared_ptr<const T> shared_from_this() const {
        return shared_ptr<const T>(weak_this);
    }

private:
    mutable weak_ptr<T> weak_this;  // 弱引用自身，避免循环引用
    friend class shared_ptr<T>;     // 允许shared_ptr修改weak_this
};

// 核心：shared_ptr类
template <typename T>
class shared_ptr {
public:
    // 1. 构造函数
    // 从原始指针构造（使用默认删除器）
    template <typename U = T, std::enable_if_t<!std::is_array_v<U>, int> = 0>
    explicit shared_ptr(U* p = nullptr) : ptr(p) {
        if (p) {
            cb = new ControlBlock<U, DefaultDeleter<U>>(p, DefaultDeleter<U>());
            // 若对象继承自enable_shared_from_this，初始化weak_this
            if constexpr (std::is_base_of_v<enable_shared_from_this<U>, U>) {
                p->weak_this = *this;
            }
        } else {
            cb = nullptr;
        }
    }

    // 数组特化：支持shared_ptr<T[]>
    template <typename U = T, std::enable_if_t<std::is_array_v<U>, int> = 0>
    explicit shared_ptr(U* p) : ptr(p) {
        using ElementType = std::remove_extent_t<U>;
        cb = new ControlBlock<ElementType[], DefaultDeleter<ElementType[]>>(
            p, DefaultDeleter<ElementType[]>()
        );
    }

    // 带自定义删除器的构造
    template <typename U, typename Deleter>
    shared_ptr(U* p, Deleter del) : ptr(p) {
        cb = new ControlBlock<U, Deleter>(p, std::move(del));
        if constexpr (std::is_base_of_v<enable_shared_from_this<U>, U>) {
            p->weak_this = *this;
        }
    }

    // 2. 拷贝构造（共享控制块，强引用+1）
    shared_ptr(const shared_ptr& other) : ptr(other.ptr), cb(other.cb)
     {
        //原子递增：读取-修改-写入整个过程不可分割
        if (cb) cb->strong_count.fetch_add(1, std::memory_order_relaxed);
    }

    // 3. 移动构造（转移所有权，不修改计数）
    shared_ptr(shared_ptr&& other) noexcept : ptr(other.ptr), cb(other.cb) {
        other.ptr = nullptr;
        other.cb = nullptr;
    }

    // 4. 从weak_ptr构造（提升弱引用，强引用+1）
    explicit shared_ptr(const weak_ptr<T>& wp) {
        if (wp.expired()) throw std::bad_weak_ptr();  // 弱引用已失效
        ptr = wp.ptr;
        cb = wp.cb;
        cb->strong_count.fetch_add(1, std::memory_order_relaxed);
    }

    // 5. 拷贝赋值
    shared_ptr& operator=(const shared_ptr& other) {
        if (this != &other) {
            reset();  // 释放当前资源
            ptr = other.ptr;
            cb = other.cb;
            if (cb) cb->strong_count.fetch_add(1, std::memory_order_relaxed);
        }
        return *this;
    }

    // 6. 移动赋值
    shared_ptr& operator=(shared_ptr&& other) noexcept {
        if (this != &other) {
            reset();  // 释放当前资源
            ptr = other.ptr;
            cb = other.cb;
            other.ptr = nullptr;
            other.cb = nullptr;
        }
        return *this;
    }

    // 7. 析构函数（强引用-1，若为0则销毁对象；弱引用-1，若为0则销毁控制块）
    ~shared_ptr() {
        reset();
    }

    // 8. 释放资源
    void reset() {
        if (cb) {
            // 强引用计数减1，若为0则销毁对象
            if (cb->strong_count.fetch_sub(1, std::memory_order_acq_rel) == 1) {
                cb->destroy();  // 调用删除器销毁对象
                // 弱引用计数减1，若为0则销毁控制块
                // 原子递减：同样不可分割
                if (cb->weak_count.fetch_sub(1, std::memory_order_acq_rel) == 1) {
                    delete cb;
                }
            }
            ptr = nullptr;
            cb = nullptr;
        }
    }

    // 9. 辅助函数
    size_t use_count() const {  // 强引用计数
        return cb ? cb->strong_count.load(std::memory_order_relaxed) : 0;
    }
    bool unique() const {  // 是否唯一引用
        return use_count() == 1;
    }
    explicit operator bool() const {  // 是否持有对象
        return ptr != nullptr;
    }

    // 10. 指针操作
    T* get() const { return ptr; }
    T& operator*() const { return *ptr; }
    T* operator->() const { return ptr; }
    // 数组访问（仅对shared_ptr<T[]>有效）
    template <typename U = T, std::enable_if_t<std::is_array_v<U>, int> = 0>
    std::remove_extent_t<U>& operator[](size_t i) const {
        return ptr[i];
    }

private:
    T* ptr;                  // 指向对象的原始指针
    ControlBlockBase* cb;    // 控制块（存储计数和删除器）

    // 允许weak_ptr访问私有成员
    friend class weak_ptr<T>;
    // 允许enable_shared_from_this通过weak_ptr构造
    template <typename U> friend class enable_shared_from_this;
};

// 11. weak_ptr实现（配合shared_ptr解决循环引用）
template <typename T>
class weak_ptr {
public:
    weak_ptr() : ptr(nullptr), cb(nullptr) {}
    weak_ptr(const shared_ptr<T>& sp) : ptr(sp.ptr), cb(sp.cb) {
        if (cb) cb->weak_count.fetch_add(1, std::memory_order_relaxed);
    }
    weak_ptr(const weak_ptr& other) : ptr(other.ptr), cb(other.cb) {
        if (cb) cb->weak_count.fetch_add(1, std::memory_order_relaxed);
    }
    weak_ptr(weak_ptr&& other) noexcept : ptr(other.ptr), cb(other.cb) {
        other.ptr = nullptr;
        other.cb = nullptr;
    }

    ~weak_ptr() {
        if (cb && cb->weak_count.fetch_sub(1, std::memory_order_acq_rel) == 1) {
            // 若强引用已为0，销毁控制块
            if (cb->strong_count.load(std::memory_order_relaxed) == 0) {
                delete cb;
            }
        }
    }

    weak_ptr& operator=(const shared_ptr<T>& sp) {
        if (cb) {
            if (cb->weak_count.fetch_sub(1, std::memory_order_acq_rel) == 1 && 
                cb->strong_count.load(std::memory_order_relaxed) == 0) {
                delete cb;
            }
        }
        ptr = sp.ptr;
        cb = sp.cb;
        if (cb) cb->weak_count.fetch_add(1, std::memory_order_relaxed);
        return *this;
    }

    weak_ptr& operator=(const weak_ptr& other) {
        if (this != &other) {
            if (cb) {
                if (cb->weak_count.fetch_sub(1, std::memory_order_acq_rel) == 1 && 
                    cb->strong_count.load(std::memory_order_relaxed) == 0) {
                    delete cb;
                }
            }
            ptr = other.ptr;
            cb = other.cb;
            if (cb) cb->weak_count.fetch_add(1, std::memory_order_relaxed);
        }
        return *this;
    }

    // 检查是否过期（强引用为0）
    bool expired() const {
        return cb ? cb->strong_count.load(std::memory_order_relaxed) == 0 : true;
    }

    // 提升为shared_ptr（若未过期）
    shared_ptr<T> lock() const {
        return expired() ? shared_ptr<T>() : shared_ptr<T>(*this);
    }

    size_t use_count() const {
        return cb ? cb->strong_count.load(std::memory_order_relaxed) : 0;
    }

private:
    T* ptr;
    ControlBlockBase* cb;
    friend class shared_ptr<T>;
};

// 辅助函数：make_shared（更高效，一次性分配对象和控制块）
template <typename T, typename... Args>
shared_ptr<T> make_shared(Args&&... args) {
    return shared_ptr<T>(new T(std::forward<Args>(args)...));
}
